/*
 * Copyright (C) 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package tako.wisers.com.android.apis.adapter;

import tako.wisers.com.android.apis.R;
import tako.wisers.com.android.apis.database.SQListManager;
import tako.wisers.com.android.apis.http.StationService;
import tako.wisers.com.android.apis.item.BaseItem;
import tako.wisers.com.android.apis.item.NewsItem;
import tako.wisers.com.android.apis.item.PanoramioItem;
import tako.wisers.com.android.apis.item.StationItem;
import tako.wisers.com.android.apis.parser.NewsHeadlineParser;

import android.content.Context;
import android.database.DataSetObserver;
import android.os.Handler;
import android.widget.Toast;

import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;

/**
 * This class is responsible for downloading and parsing the search results for
 * a particular area. All of the work is done on a separate thread, and progress
 * is reported back through the DataSetObserver set in
 * {@link #addObserver(DataSetObserver). State is held in memory by in memory
 * maintained by a single instance of the ImageManager class.
 */
public class ListManager {
	/**
	 * Used to post results back to the UI thread
	 */
	private Handler mHandler = new Handler();

	/**
	 * Holds the single instance of a ImageManager that is shared by the
	 * process.
	 */
	private static ListManager sInstance;

	/**
	 * Holds the images and related data that have been downloaded
	 */
	private List<BaseItem> mItems = new ArrayList<BaseItem>();

	/**
	 * Observers interested in changes to the current search results
	 */
	private ArrayList<WeakReference<DataSetObserver>> mObservers = new ArrayList<WeakReference<DataSetObserver>>();

	/**
	 * True if we are in the process of loading
	 */
	private boolean mLoading;

	private Context mContext;

	/**
	 * Key for an Intent extra. The value is the zoom level selected by the
	 * user.
	 */
	public static final String ZOOM_EXTRA = "zoom";

	/**
	 * Key for an Intent extra. The value is an item to display
	 */
	public static final String PANORAMIO_ITEM_EXTRA = "item";

	public static ListManager getInstance(Context c) {
		if (sInstance == null) {
			sInstance = new ListManager(c.getApplicationContext());
		}
		return sInstance;
	}

	private ListManager(Context c) {
		mContext = c;
	}

	/**
	 * @return True if we are still loading content
	 */
	public boolean isLoading() {
		return mLoading;
	}

	/**
	 * Clear all downloaded content
	 */
	public void clear() {
		mHandler.post(new Runnable() {
			public void run() {
				mItems.clear();
				notifyObservers();
			}
		});
	}

	/**
	 * Add an item to and notify observers of the change.
	 * 
	 * @param item
	 *            The item to add
	 */
	private void add(BaseItem item) {
		mItems.add(item);
		notifyObservers();
	}

	/**
	 * @return The number of items displayed so far
	 */
	public int size() {
		return mItems.size();
	}

	/**
	 * Gets the item at the specified position
	 */
	public BaseItem get(int position) {
		return mItems.get(position);
	}

	/**
	 * Adds an observer to be notified when the set of items held by this
	 * ImageManager changes.
	 */
	public void addObserver(DataSetObserver observer) {
		WeakReference<DataSetObserver> obs = new WeakReference<DataSetObserver>(
				observer);
		mObservers.add(obs);
	}

	/**
	 * Load a new set of search results for the specified area.
	 * 
	 * @param minLong
	 *            The minimum longitude for the search area
	 * @param maxLong
	 *            The maximum longitude for the search area
	 * @param minLat
	 *            The minimum latitude for the search area
	 * @param maxLat
	 *            The minimum latitude for the search area
	 */
	public void loadPanoramio(List<PanoramioItem> items) {
		setItemList(items);
	}

	// public void loadPanoramioForMap(float minLong, float maxLong, float
	// minLat,
	// float maxLat) {
	// clear();
	// networdExecute(minLong, maxLong, minLat, maxLat);
	// }

	public void loadStation(List<StationItem> items) {
		setItemList(items);
	}

	// class NetworkThread extends Thread {
	// private List<? extends BaseItem> itemList;
	//
	// public NetworkThread(List<? extends BaseItem> itemList) {
	// this.itemList = itemList;
	// start();
	// }
	//
	// @Override
	// public void run() {
	// setItemList(itemList);
	// }
	// }

	private void setItemList(List<? extends BaseItem> itemList) {
		if (itemList == null)
			return;
		clear();
		int count = itemList.size();
		for (int i = 0; i < count; i++) {
			final BaseItem item = itemList.get(i);
			final boolean done = i == count - 1;
			if (item == null)
				continue;
			mHandler.post(new Runnable() {
				public void run() {
					sInstance.mLoading = !done;
					sInstance.add(item);
				}
			});
		}
	}

	public void loadNews(List<NewsItem> items) {
		setItemList(items);
	}

	/**
	 * Called when something changes in our data set. Cleans up any weak
	 * references that are no longer valid along the way.
	 */
	private void notifyObservers() {
		final ArrayList<WeakReference<DataSetObserver>> observers = mObservers;
		final int count = observers.size();
		for (int i = count - 1; i >= 0; i--) {
			WeakReference<DataSetObserver> weak = observers.get(i);
			DataSetObserver obs = weak.get();
			if (obs != null) {
				obs.onChanged();
			} else {
				observers.remove(i);
			}
		}

	}

	public List<BaseItem> getItems() {
		return mItems;
	}

}
